package xyz.lwm.lazycat.utility.convert;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;

/**
 * check type
 *
 * @author lwm
 */
public abstract class Types {

    /**
     * is primitive type or wrap type
     *
     * @param type class
     * @return true if is primitive type or wrap type
     */
    public static boolean isPrimitiveType(Class<?> type) {
        return type.isPrimitive() ||
                type == String.class || type == Boolean.class || type == Character.class ||
                type == Byte.class || type == Short.class || type == Integer.class || type == Long.class ||
                type == Float.class || type == Double.class || type == Void.class;
    }

    /**
     * is date type (util date, sql date, time, timestamp, localDate, LocalTime, localDateTime, duration, calendar)
     *
     * @param type class
     * @return true if is date type
     */
    public static boolean isDateType(Class<?> type) {
        return type == Date.class || type == java.sql.Date.class || type == java.sql.Time.class || type == java.sql.Timestamp.class ||
                type == LocalDate.class || type == LocalTime.class || type == LocalDateTime.class || type == Duration.class || type == Calendar.class;
    }

    /**
     * is char sequence type (string, stringBuilder, stringBuffer...)
     *
     * @param type class
     * @return true if is char sequence type
     */
    public static boolean isCharSequenceType(Class<?> type) {
        return CharSequence.class.isAssignableFrom(type);
    }

    /**
     * is numeric type (byte, short, int, long, float, double, BigInteger, BigDecimal)
     *
     * @param type class
     * @return true if is numeric type
     */
    public static boolean isNumericType(Class<?> type) {
        return type == Byte.class || type == Short.class || type == Integer.class || type == Long.class ||
                type == Float.class || type == Double.class || type == BigInteger.class || type == BigDecimal.class;
    }

    /**
     * is enum type
     *
     * @param type class
     * @return true if is enum type
     */
    public static boolean isEnumType(Class<?> type) {
        return type.isEnum();
    }

    /**
     * is base type (primitive type or wrap type, date type, char sequence type, numeric type, enum type)
     *
     * @param type class
     * @return true if is base type
     */
    public static boolean isBaseType(Class<?> type) {
        return isPrimitiveType(type) || isDateType(type) || isCharSequenceType(type) || isNumericType(type) || isEnumType(type);
    }

    /**
     * is array type
     *
     * @param type class
     * @return true if is array type
     */
    public static boolean isArrayType(Class<?> type) {
        return type.isArray();
    }

    /**
     * is collection type
     *
     * @param type class
     * @return true if is collection type
     */
    public static boolean isCollectionType(Class<?> type) {
        return Collection.class.isAssignableFrom(type);
    }

    /**
     * is bean type
     *
     * @param type class
     * @return true if is bean type
     */
    public static boolean isBeanType(Class<?> type) {
        return !isPrimitiveType(type) && !isDateType(type) && !isCharSequenceType(type) &&
                !isNumericType(type) && !isEnumType(type) && !isArrayType(type) && !isCollectionType(type);
    }

}
